#include "Lista.h"

/* Constructor de la clase lista
Pre: Lista no creado
Post: Devuelve una instancia v�lida */
Lista::Lista() {
	this->actual = this->primero = 0;
	this->size = 0;
}

/* Destructor de la lista
Pre: Lista creada
Post: Lista eliminada */
Lista::~Lista() {
}

/* avanzar()
Pre: lista  creada y no vacia
Post: avanza la lista apunta al siguietne elemento
	devuelev 1 si hay siguiente y 0 si es el fin */
int Lista::avanzar() {
	/* avanza en la lista un nodo. Si existe el siguiente
	 * devuelve 1  y sino hay mas elementos devuelve 0
	 */
	if (this->actual->hay_siguiente()) {
		this->actual = this->actual->get_siguiente();
		return HAY_SIGUIENTE;
	}
	else return NO_SIGUIENTE;
}

/* lista_vacia
Pre: Lista creada
Post: Devuelve 1 si la lista vacia y 0 en caso contrario */
int Lista:: lista_vacia() {
	if (this->primero) return LISTA_NO_VACIA;
	else return LISTA_VACIA;
}

/* obtener_elem()
Pre: Lista creada y no vacia
Post: Devuelve el elemento del nodo actual */
void* Lista:: obtener_elem() {
	return (this->actual->devolver_elem());
}

/* insertar_lista
Pre: Lista credada
Post: Inserta una movida en la lista */
void Lista:: insertar_lista(Termino* elem) {
	   Nodo* nodo = new Nodo;
	   nodo->agregar_elem(elem);
	   if (this->lista_vacia()) {
		   this->actual = this->primero = nodo;
	   }
	   /* Sino lo añado al siguiente del nodo actual*/
	   else {
		   while(this->avanzar()){};
		   this->actual->set_siguiente(nodo);
		   this->actual = this->actual->get_siguiente();
	   }
}

 void Lista::agregar_nodo(Nodo* nodo) {
	if (nodo != NULL) {
		   if (this->lista_vacia()) {
			   this->actual = this->primero = nodo;
		   }
		   /* Sino lo añado al siguiente del nodo actual*/
		   else {
			   while(this->avanzar()){};
			   this->actual->set_siguiente(nodo);
			   nodo->set_anterior(this->actual);
			   this->actual = this->actual->get_siguiente();
		   }
		  Termino* ter =  nodo->devolver_elem();
		  if (ter != NULL) {
			  this->size = 4 + 4 + ter->getLong() + this->size;
		  }
	}
}

Nodo* Lista::obtener_actual() {
	return this->actual;
}
 /* avanzar_primero
Pre: lista creada y no vacia
Post: apunta el nodo actual al primer nodo*/
void Lista::avanzar_primero() {
	this->actual = this->primero;
}

void Lista::grabar(FILE* salida, int modo) {
	if (!this->lista_vacia());
	this->avanzar_primero();
	do {
		this->actual->grabar(salida, modo);
	} while (this->avanzar());
}

char* Lista::grabar() {
	char* buffer = new char[this->size];
	if (!this->lista_vacia()) {
		int pos_actual = 0;
		this->avanzar_primero();
		do {
			this->actual->grabar(buffer, &pos_actual);
		} while (this->avanzar());
	}
	return buffer;
}

void Lista::quitar(Nodo* nodo) {
	Nodo*  ant = nodo->get_anterior();
	Nodo* sig = nodo->get_siguiente();
	if (this->primero == nodo) {
		this->primero = sig;
	}
	if (this->actual == nodo) {
		this->actual = nodo->get_siguiente();
	}
	if (ant != 0) {
	ant->set_siguiente(sig);
	}
	if (sig!=0) {
	sig->set_anterior(ant);
	}
	nodo->set_siguiente(0);
	nodo->set_anterior(0);
}

void Lista::vaciar() {
	/* elimina la lista, recorriendoal por completo
	 * y vaciando sus nodos
	 */
	Nodo *actual, *siguiente;
	actual = this->primero;
	while (actual != NULL) {
		siguiente = actual->get_siguiente();
		delete(actual);
		actual = siguiente;
	}
	this->actual = this->primero = NULL;
}

int Lista::get_size() {
	return this->size;
}
